import { nextTick } from 'vue'
import { dataLoaderService, LoadPriority } from './dataLoaderService'

// 渲染阶段定义
export enum RenderPhase {
  SKELETON = 'skeleton',        // 骨架屏
  LAYOUT = 'layout',           // 布局渲染
  CRITICAL_DATA = 'critical',   // 关键数据
  SECONDARY_DATA = 'secondary', // 次要数据
  BACKGROUND_DATA = 'background' // 后台数据
}

// 渲染任务接口
export interface RenderTask {
  id: string
  phase: RenderPhase
  priority: number
  execute: () => Promise<void>
  dependencies?: string[]
  timeout?: number
}

// 虚拟化配置
export interface VirtualizationConfig {
  itemHeight: number
  bufferSize: number
  threshold: number
  enableDynamicHeight: boolean
}

/**
 * 页面渲染优化服务
 * 实现分阶段渲染、虚拟化、防抖等优化策略
 */
export class RenderOptimizationService {
  private renderTasks: Map<string, RenderTask> = new Map()
  private completedTasks: Set<string> = new Set()
  private isRendering = false
  // private renderQueue: RenderTask[] = [] // TODO: Implement render queue functionality
  private debounceTimers: Map<string, NodeJS.Timeout> = new Map()
  private intersectionObserver?: IntersectionObserver
  private resizeObserver?: ResizeObserver

  constructor() {
    this.initializeObservers()
  }

  /**
   * 启动分阶段渲染流程
   */
  async startPhaseRendering(workspaceId: string): Promise<void> {
    console.log(`[RenderOptimization] 开始分阶段渲染工作区: ${workspaceId}`)
    
    // 清理之前的任务
    this.clearTasks()
    
    // 注册渲染任务
    this.registerRenderTasks(workspaceId)
    
    // 开始渲染流程
    await this.executeRenderPhases()
  }

  /**
   * 注册渲染任务
   */
  private registerRenderTasks(workspaceId: string): void {
    // 阶段1: 骨架屏渲染
    this.addRenderTask({
      id: 'skeleton',
      phase: RenderPhase.SKELETON,
      priority: 1,
      execute: async () => {
        await this.renderSkeleton()
      }
    })

    // 阶段2: 布局渲染
    this.addRenderTask({
      id: 'layout',
      phase: RenderPhase.LAYOUT,
      priority: 2,
      dependencies: ['skeleton'],
      execute: async () => {
        await this.renderLayout(workspaceId)
      }
    })

    // 阶段3: 关键数据渲染
    this.addRenderTask({
      id: 'critical-data',
      phase: RenderPhase.CRITICAL_DATA,
      priority: 3,
      dependencies: ['layout'],
      execute: async () => {
        await this.renderCriticalData(workspaceId)
      }
    })

    // 阶段4: 次要数据渲染
    this.addRenderTask({
      id: 'secondary-data',
      phase: RenderPhase.SECONDARY_DATA,
      priority: 4,
      dependencies: ['critical-data'],
      execute: async () => {
        await this.renderSecondaryData(workspaceId)
      }
    })

    // 阶段5: 后台数据加载
    this.addRenderTask({
      id: 'background-data',
      phase: RenderPhase.BACKGROUND_DATA,
      priority: 5,
      dependencies: ['secondary-data'],
      execute: async () => {
        await this.loadBackgroundData(workspaceId)
      }
    })
  }

  /**
   * 添加渲染任务
   */
  addRenderTask(task: RenderTask): void {
    this.renderTasks.set(task.id, task)
  }

  /**
   * 执行渲染阶段
   */
  private async executeRenderPhases(): Promise<void> {
    if (this.isRendering) return
    this.isRendering = true

    try {
      // 按优先级和依赖关系排序任务
      const sortedTasks = this.sortTasksByDependencies()
      
      for (const task of sortedTasks) {
        if (this.completedTasks.has(task.id)) continue
        
        console.log(`[RenderOptimization] 执行渲染任务: ${task.id} (${task.phase})`)
        
        const startTime = performance.now()
        
        try {
          // 设置超时
          const timeoutPromise = task.timeout ? 
            new Promise((_, reject) => 
              setTimeout(() => reject(new Error(`Task ${task.id} timeout`)), task.timeout)
            ) : Promise.resolve()
          
          await Promise.race([
            task.execute(),
            timeoutPromise
          ])
          
          this.completedTasks.add(task.id)
          
          const duration = performance.now() - startTime
          console.log(`[RenderOptimization] 任务 ${task.id} 完成，耗时: ${duration.toFixed(2)}ms`)
          
          // 让出控制权，避免阻塞UI
          await nextTick()
          
        } catch (error) {
          console.error(`[RenderOptimization] 任务 ${task.id} 执行失败:`, error)
          // 继续执行其他任务
        }
      }
    } finally {
      this.isRendering = false
    }
  }

  /**
   * 按依赖关系排序任务
   */
  private sortTasksByDependencies(): RenderTask[] {
    const tasks = Array.from(this.renderTasks.values())
    const sorted: RenderTask[] = []
    const visited = new Set<string>()
    const visiting = new Set<string>()

    const visit = (task: RenderTask) => {
      if (visiting.has(task.id)) {
        throw new Error(`Circular dependency detected: ${task.id}`)
      }
      if (visited.has(task.id)) return

      visiting.add(task.id)
      
      if (task.dependencies) {
        for (const depId of task.dependencies) {
          const depTask = this.renderTasks.get(depId)
          if (depTask) {
            visit(depTask)
          }
        }
      }
      
      visiting.delete(task.id)
      visited.add(task.id)
      sorted.push(task)
    }

    // 按优先级排序后访问
    tasks.sort((a, b) => a.priority - b.priority)
    for (const task of tasks) {
      visit(task)
    }

    return sorted
  }

  /**
   * 渲染骨架屏
   */
  private async renderSkeleton(): Promise<void> {
    // 显示骨架屏，隐藏加载指示器
    const skeletonElements = document.querySelectorAll('.skeleton-placeholder')
    skeletonElements.forEach(el => {
      (el as HTMLElement).style.display = 'block'
    })
    
    const loadingElements = document.querySelectorAll('.loading-spinner')
    loadingElements.forEach(el => {
      (el as HTMLElement).style.display = 'none'
    })
    
    await new Promise(resolve => setTimeout(resolve, 50)) // 确保DOM更新
  }

  /**
   * 渲染布局
   */
  private async renderLayout(workspaceId: string): Promise<void> {
    // workspaceId 参数保留用于未来的工作区特定布局配置
    console.debug('Rendering layout for workspace:', workspaceId)
    
    // 渲染基本布局结构
    const layoutElements = document.querySelectorAll('.layout-container')
    layoutElements.forEach(el => {
      (el as HTMLElement).style.visibility = 'visible'
    })
    
    // 初始化可调整大小的面板
    this.initializeResizablePanels()
    
    await nextTick()
  }

  /**
   * 渲染关键数据
   */
  private async renderCriticalData(workspaceId: string): Promise<void> {
    // 加载并渲染组件列表（最重要的数据）
    const componentList = await dataLoaderService.loadComponentList(workspaceId, LoadPriority.IMMEDIATE)
    
    // 触发组件列表渲染
    this.triggerComponentListRender(componentList)
    
    // 加载目录结构
    await dataLoaderService.loadDirectoryStructure(workspaceId, LoadPriority.HIGH)
    
    // 隐藏骨架屏，显示实际内容
    const skeletonElements = document.querySelectorAll('.skeleton-placeholder')
    skeletonElements.forEach(el => {
      (el as HTMLElement).style.display = 'none'
    })
    
    await nextTick()
  }

  /**
   * 渲染次要数据
   */
  private async renderSecondaryData(workspaceId: string): Promise<void> {
    // 加载转储文件路径
    await dataLoaderService.loadDumpFilePaths(workspaceId, LoadPriority.NORMAL)
    
    // 加载基础日志数据（不包含详细内容）
    const logTypes = ['operation', 'framework', 'app']
    const loadTasks = logTypes.map(type => 
      dataLoaderService.loadLogData(workspaceId, type, LoadPriority.NORMAL)
    )
    
    await Promise.allSettled(loadTasks)
    
    await nextTick()
  }

  /**
   * 加载后台数据
   */
  private async loadBackgroundData(workspaceId: string): Promise<void> {
    // 预加载转储数据
    const dumpTypes: ('framework' | 'operation' | 'app')[] = ['framework', 'operation', 'app']
    const preloadTasks = dumpTypes.map(type => 
      dataLoaderService.preloadDumpData(workspaceId, type)
    )
    
    await Promise.allSettled(preloadTasks)
    
    console.log(`[RenderOptimization] 后台数据加载完成`)
  }

  /**
   * 触发组件列表渲染
   */
  private triggerComponentListRender(componentList: any[]): void {
    // 发送自定义事件通知组件更新
    const event = new CustomEvent('componentListLoaded', {
      detail: { components: componentList }
    })
    document.dispatchEvent(event)
  }

  /**
   * 初始化可调整大小的面板
   */
  private initializeResizablePanels(): void {
    const resizableElements = document.querySelectorAll('.resizable-panel')
    resizableElements.forEach(el => {
      // 添加调整大小的逻辑
      this.makeElementResizable(el as HTMLElement)
    })
  }

  /**
   * 使元素可调整大小
   */
  private makeElementResizable(element: HTMLElement): void {
    // 简化的可调整大小实现
    element.style.resize = 'both'
    element.style.overflow = 'auto'
  }

  /**
   * 防抖函数
   */
  debounce<T extends (...args: any[]) => any>(
    key: string,
    func: T,
    delay: number
  ): (...args: Parameters<T>) => void {
    return (...args: Parameters<T>) => {
      const existingTimer = this.debounceTimers.get(key)
      if (existingTimer) {
        clearTimeout(existingTimer)
      }
      
      const timer = setTimeout(() => {
        func(...args)
        this.debounceTimers.delete(key)
      }, delay)
      
      this.debounceTimers.set(key, timer)
    }
  }

  /**
   * 创建虚拟列表
   */
  createVirtualList(config: VirtualizationConfig) {
    return {
      itemHeight: config.itemHeight,
      bufferSize: config.bufferSize,
      threshold: config.threshold,
      
      // 计算可见范围
      calculateVisibleRange(scrollTop: number, containerHeight: number, totalItems: number) {
        const startIndex = Math.floor(scrollTop / config.itemHeight)
        const endIndex = Math.min(
          startIndex + Math.ceil(containerHeight / config.itemHeight) + config.bufferSize,
          totalItems - 1
        )
        
        return {
          startIndex: Math.max(0, startIndex - config.bufferSize),
          endIndex,
          visibleItems: endIndex - startIndex + 1
        }
      },
      
      // 获取项目样式
      getItemStyle(index: number) {
        return {
          position: 'absolute' as const,
          top: `${index * config.itemHeight}px`,
          height: `${config.itemHeight}px`,
          width: '100%'
        }
      }
    }
  }

  /**
   * 初始化观察者
   */
  private initializeObservers(): void {
    // 交叉观察者，用于懒加载
    this.intersectionObserver = new IntersectionObserver(
      (entries) => {
        entries.forEach(entry => {
          if (entry.isIntersecting) {
            const element = entry.target as HTMLElement
            const loadAction = element.dataset.lazyLoad
            if (loadAction) {
              this.handleLazyLoad(loadAction, element)
            }
          }
        })
      },
      {
        rootMargin: '100px' // 提前100px开始加载
      }
    )

    // 尺寸观察者，用于响应式布局
    this.resizeObserver = new ResizeObserver(
      this.debounce('resize', (entries: ResizeObserverEntry[]) => {
        entries.forEach((entry: ResizeObserverEntry) => {
          this.handleElementResize(entry.target as HTMLElement, entry.contentRect)
        })
      }, 100)
    )
  }

  /**
   * 处理懒加载
   */
  private async handleLazyLoad(action: string, element: HTMLElement): Promise<void> {
    try {
      switch (action) {
        case 'component-logs':
          const componentName = element.dataset.componentName
          if (componentName) {
            await this.loadComponentLogs(componentName, element)
          }
          break
        case 'log-content':
          const logType = element.dataset.logType
          if (logType) {
            await this.loadLogContent(logType, element)
          }
          break
      }
    } catch (error) {
      console.error(`[RenderOptimization] 懒加载失败: ${action}`, error)
    }
  }

  /**
   * 加载组件日志
   */
  private async loadComponentLogs(componentName: string, element: HTMLElement): Promise<void> {
    const workspaceId = element.dataset.workspaceId
    if (!workspaceId) return

    const logs = await dataLoaderService.loadComponentLogs(workspaceId, componentName, LoadPriority.HIGH)
    
    // 触发组件更新
    const event = new CustomEvent('componentLogsLoaded', {
      detail: { componentName, logs, element }
    })
    element.dispatchEvent(event)
  }

  /**
   * 加载日志内容
   */
  private async loadLogContent(logType: string, element: HTMLElement): Promise<void> {
    const workspaceId = element.dataset.workspaceId
    if (!workspaceId) return

    const logData = await dataLoaderService.loadLogData(workspaceId, logType, LoadPriority.HIGH)
    
    // 触发内容更新
    const event = new CustomEvent('logContentLoaded', {
      detail: { logType, logData, element }
    })
    element.dispatchEvent(event)
  }

  /**
   * 处理元素尺寸变化
   */
  private handleElementResize(element: HTMLElement, rect: DOMRectReadOnly): void {
    // 更新虚拟列表的容器尺寸
    if (element.classList.contains('virtual-list-container')) {
      const event = new CustomEvent('virtualListResize', {
        detail: { width: rect.width, height: rect.height }
      })
      element.dispatchEvent(event)
    }
  }

  /**
   * 观察元素
   */
  observeElement(element: HTMLElement, type: 'intersection' | 'resize' = 'intersection'): void {
    if (type === 'intersection' && this.intersectionObserver) {
      this.intersectionObserver.observe(element)
    } else if (type === 'resize' && this.resizeObserver) {
      this.resizeObserver.observe(element)
    }
  }

  /**
   * 停止观察元素
   */
  unobserveElement(element: HTMLElement, type: 'intersection' | 'resize' = 'intersection'): void {
    if (type === 'intersection' && this.intersectionObserver) {
      this.intersectionObserver.unobserve(element)
    } else if (type === 'resize' && this.resizeObserver) {
      this.resizeObserver.unobserve(element)
    }
  }

  /**
   * 清理任务
   */
  private clearTasks(): void {
    this.renderTasks.clear()
    this.completedTasks.clear()
    // this.renderQueue = [] // TODO: Implement render queue functionality
  }

  /**
   * 获取渲染统计信息
   */
  getRenderStats() {
    return {
      totalTasks: this.renderTasks.size,
      completedTasks: this.completedTasks.size,
      isRendering: this.isRendering,
      pendingTasks: this.renderTasks.size - this.completedTasks.size
    }
  }

  /**
   * 销毁服务
   */
  destroy(): void {
    // 清理观察者
    if (this.intersectionObserver) {
      this.intersectionObserver.disconnect()
    }
    if (this.resizeObserver) {
      this.resizeObserver.disconnect()
    }
    
    // 清理定时器
    this.debounceTimers.forEach(timer => clearTimeout(timer))
    this.debounceTimers.clear()
    
    // 清理任务
    this.clearTasks()
  }
}

// 全局渲染优化服务实例
export const renderOptimizationService = new RenderOptimizationService()